/*
* Copyright 2009 NOR_/D Labs <http://labs.nortd.com>
*
* This file is part of SceneExpression.
* SceneExpression is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License 
* as published by the Free Software Foundation, either version 3 of 
* the License, or (at your option) any later version. For details
* see <http://www.gnu.org/licenses/>.
*
* * *
* 
*/


#include <sx/CheckboxWidget.h>
#include <sx/Shape.h>

using namespace sx;


// CheckboxNob
//

CheckboxNob::CheckboxNob( CheckboxWidget* checkbox ) {
    _bChecked = false;
    _checkbox = checkbox;
    _bFlipping = false;
    _flipAngle = 0.0f;
    _bReached90deg = false;
    _bAnimate = true;
    
    _width = _height= 100;
    
    _checkshape = new Shape();
    _checkshape->setMode(osg::PrimitiveSet::LINES);
    _checkshape->setColor(0.5f, 0.5f, 0.5f, 1.0f);
    addChild(_checkshape.get());
    _checkshape->setVisible(false);
    
    //state - line
    osg::StateSet* stateset = _checkshape->getOsgGeode()->getOrCreateStateSet();
    stateset->setMode(GL_LINE_SMOOTH, osg::StateAttribute::ON);
    osg::LineWidth* lw = new osg::LineWidth(4.0);
    stateset->setAttributeAndModes(lw, osg::StateAttribute::ON);
}

void CheckboxNob::setValue( bool checked ) {
    if( checked != _bChecked) {
        _bChecked = checked;
        
        if(_bAnimate) {
            _bFlipping = true;
            _flipTimer.setStartTick();
        } else {
            _checkshape->setVisible(_bChecked);
        }
        
        // delegate on-change to registered handlers
        for( unsigned int i=0; i<_checkbox->getEventHandlers().size(); i++) {
            _checkbox->getEventHandlers()[i]->widgetCheckbox( *_checkbox );
        }                
    }
}

void CheckboxNob::reshape() {
    _backgroundVertices->clear();
    addRoundedRect(0.0f, 0.0f, _width, _height, 6.0f, _backgroundVertices.get());
    _backgroundDrawArray->setCount(_backgroundVertices->size());
    _borderDrawArray->setCount(_backgroundVertices->size());
    
    //check shape
    _checkshape->clearVertices();
    _checkshape->addVertex(0.25*_width, 0.25*_height, 0.0f);
    _checkshape->addVertex(0.75*_width, 0.75*_height, 0.0f);
    _checkshape->addVertex(0.25*_width, 0.75*_height, 0.0f);
    _checkshape->addVertex(0.75*_width, 0.25*_height, 0.0f);
}

void CheckboxNob::update() {
    if( _bFlipping ) {
        _flipAngle = 8*_flipTimer.time_s();
        if( _flipAngle >= osg::PI/1.8f && !_bReached90deg ) {
            _bReached90deg = true;
            //half of ratation => show/hide check shape
            if(_checkbox->getValue()) {
                _checkshape->setVisible(true);
            } else {
                _checkshape->setVisible(false);
            }
        } else if (_flipAngle >= osg::PI) {
            //end of rotation
            _flipAngle = 0;
            _bFlipping = false;
            _bReached90deg = false;       
        }
        setRotation( _flipAngle, 0.0f, 1.0f, 0.0f );
    }
}




// Checkbox
//

CheckboxWidget::CheckboxWidget() {    
    // label
    _label = new  osgText::Text;
    _geode->addDrawable( _label.get() );
    _defaultTypeface = "TitilliumText400wt.ttf";
    _label->setAlignment(osgText::Text::LEFT_CENTER);

    // setup slider nob geometry
    _nob = new CheckboxNob(this);
    addChild(_nob);
    
    setPosition(0.0f, 0.0f, 0.0f);
    setShape(100, 25);
    setBackgroundColor(0.0f, 0.0f, 0.0f, 0.2f);
    
    _buttonPressBorderColor.set(1.0f, 1.0f, 1.0f, 1.0f);
}

CheckboxWidget::~CheckboxWidget() { 
    delete _nob;
}

void CheckboxWidget::setValue( bool checked ) {
    _nob->setValue(checked);
}

bool CheckboxWidget::getValue() {
    return _nob->_bChecked;
}

void CheckboxWidget::setLabelColor( float r, float g, float b, float a ) {
    _label->setColor(osg::Vec4(r,g,b,a));
}

void CheckboxWidget::addEventHandler( CheckboxHandler* handler ){
    _handlers.push_back( handler );
}
std::vector<CheckboxHandler*>&  CheckboxWidget::getEventHandlers() {
    return _handlers;
}
        

void CheckboxWidget::reshape() {
    // define geometry
    _backgroundVertices->clear();
    //setBackgroundColor(0.2f, 0.0f, 0.0f, 0.5f);
    addRoundedRect(0.0f, 0.0f, _width, _height, 6.0f, _backgroundVertices.get());
    _backgroundDrawArray->setCount(_backgroundVertices->size());
    //_borderDrawArray->setCount(_backgroundVertices->size());
    
    //label
    setLabelColor(1.0f, 1.0f, 1.0f, 1.0f);
    _label->setFont(_defaultTypeface);
    _label->setText(getName());
    _label->setPosition(osg::Vec3(1.4*_height, _height/2.0f, 0.0f));
    _label->setCharacterSize(_height/2.5f);
    _label->setMaximumWidth(_width - 1.4*_height);
    _label->setMaximumHeight(_height);
    
    //nob
    _nob->setShape(_height, _height);
    _nob->setBackgroundColor(0.0f, 0.0f, 0.0f, 1.0f);
    _nob->setBorderColor(0.5f, 0.5f, 0.5f, 0.8f);
    _nob->setPivot(0.5*_nob->getWidth(), 0.5*_nob->getHeight(), 0.f);
    _nob->setPosition(0.5*_nob->getWidth(), 0.5*_nob->getHeight(), 0.0);    
}


// Events
//
bool CheckboxWidget::touchDown( Touch& touch ) {
    _buttonPressBorderColorTemp = _nob->getBorderColor();
    _nob->setBorderColor(_buttonPressBorderColor);    
    return true;
}  
bool CheckboxWidget::touchMove( Touch& touch ) {
    //std::cout << "touchMove on: " << getName() << std::endl;
    return true;
}
bool CheckboxWidget::touchUp( Touch& touch ) {
    _nob->setBorderColor(_buttonPressBorderColorTemp);
    
    // only trigger if still inside widget
    osg::Vec3& touchpos = touch.getLocalPosition();
    if( touchpos[0] > 0 && touchpos[0] < _width && touchpos[1] > 0 && touchpos[1] < _height ) {
        setValue( !_nob->_bChecked );
    }
    return true;
}
    
